package org.maiyoframework.core.jpa;

import java.lang.reflect.InvocationTargetException;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.SingularAttribute;

import org.maiyoframework.core.common.BeanUtils;
import org.maiyoframework.core.web.page.PageResult;

/**
 * JPA DAO支持类 
 * 提供EntityManager，分页、列表、统计基础方法
 * 
 * @author maiYo
 * 
 * @param <T>
 */
@SuppressWarnings("unchecked")
public abstract class DaoSupport<T> {

	
	public Long countResult(Finder finder) {
		String beanName = BeanUtils.getEntityClassName(entityClass);
		Query query = em.createQuery("select count(bean) from " + beanName
				+ " bean" + finder.createWhere());
		// 设置占位符实际参数
		finder.setParameters(query);
		// 记录总条数存入TotalCount中
		return (Long) query.getSingleResult();
	}

	// 获取分页数据
	public PageResult<T> getPageResult(Finder finder, int start, int pageSize) {
		PageResult<T> pageResult = new PageResult<T>();
		String beanName = BeanUtils.getEntityClassName(entityClass);
		Query query = em.createQuery("select bean from " + beanName + " bean"
				+ finder.createWhere() + finder.createOrderBy());
		// Start，pageSize任一为-1,则查询全部
		if (start != -1 && pageSize != -1)
			query.setFirstResult(start).setMaxResults(pageSize);
		finder.setParameters(query);
		pageResult.setResultList(query.getResultList());
		// 查询记录总条数
		query = em.createQuery("select count(bean) from " + beanName + " bean"
				+ finder.createWhere());
		// 设置占位符实际参数
		finder.setParameters(query);
		// 记录总条数存入TotalCount中
		pageResult.setTotalCount((Long) query.getSingleResult());
		// 返回结果集
		return pageResult;
	}
	
	protected void copyToPersistentObject(T entity, EntityType<T> cm, T po,
			String id) throws IllegalArgumentException, SecurityException,
			IllegalAccessException, InvocationTargetException,
			NoSuchMethodException {
		Object value;
		Set<SingularAttribute<? super T, ?>> singularAttributes = cm.getSingularAttributes();
		for (SingularAttribute<?, ?> sa : singularAttributes) {
			String propertyName = sa.getName(); // 获取元数据属性名
			if (propertyName.equals(id)) {
				continue;
			}
			value = entityClass.getMethod(
					BeanUtils.catchGetMethodByProperty(propertyName)).invoke(
					entity);
			if (value != null) {
				entityClass.getMethod(
						BeanUtils.catchSetMethodByProperty(propertyName),
						sa.getJavaType()).invoke(po, value);
			}
		}
	}

	@PersistenceContext
	protected EntityManager em;

	// 程序运行时，当前类将作为基类被继承，通过反射工具类getGenericClass，得到此时泛型 所指定的实际型参数类型
	protected Class<T> entityClass = BeanUtils
			.getGenericClass(this.getClass());

}
